using B.S.XZYData.Api.Wrter.Application.Command.WorkReport;
using DomainWorkReport = B.S.XZYData.Domain.ZSH.WorkReport;
using DomainWorkReportDefectiveItem = B.S.XZYData.Domain.ZSH.WorkReportDefectiveItem;
using B.S.XZYData.Domain.ZSH;
using B.S.XZYData.ErrorCode;
using B.S.XZYData.Infrastructure.Interface;
using MediatR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Transactions;
using System.Text.Json;

namespace B.S.XZYData.Api.Wrter.Application.Handler.WorkReport
{
    /// <summary>
    /// 新增报工处理器
    /// </summary>
    public class AddWorkReportHandler : IRequestHandler<AddWorkReportCommand, ApiResult<int>>
    {
        private readonly IBaseRepository<DomainWorkReport> _workReportRepo;
        private readonly IBaseRepository<DomainWorkReportDefectiveItem> _defectiveItemRepo;
        private readonly IBaseRepository<WorkflowInstanceModel> _workflowInstanceRepo;

        public AddWorkReportHandler(IBaseRepository<DomainWorkReport> workReportRepo,
                                     IBaseRepository<DomainWorkReportDefectiveItem> defectiveItemRepo,
                                     IBaseRepository<WorkflowInstanceModel> workflowInstanceRepo)
        {
            _workReportRepo = workReportRepo;
            _defectiveItemRepo = defectiveItemRepo;
            _workflowInstanceRepo = workflowInstanceRepo;
        }

        public async Task<ApiResult<int>> Handle(AddWorkReportCommand request, CancellationToken cancellationToken)
        {
            var res = new ApiResult<int>();

            // 基本校验
            if (string.IsNullOrWhiteSpace(request.WorkOrderCode))
            {
                res.Code = ApiEnum.Fail;
                res.Msg = "工单编号不能为空";
                return await Task.FromResult(res);
            }
            if (request.ReportQty <= 0)
            {
                res.Code = ApiEnum.Fail;
                res.Msg = "报工数量必须大于0";
                return await Task.FromResult(res);
            }

            try
            {
                using var scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled);

                // 创建主表实体
                var workReport = new DomainWorkReport
                {
                    WorkOrderCode = request.WorkOrderCode,
                    ProcessName = request.ProcessName,
                    ProductCode = request.ProductCode,
                    ProductNo = request.ProductNo,
                    ProductName = request.ProductName,
                    ProductSpec = request.ProductSpec,
                    ReportQty = request.ReportQty,
                    Producer = request.Producer,
                    Unit = request.Unit,
                    GoodQty = request.GoodQty,
                    DefectiveQty = request.DefectiveQty,
                    ProcessStatus = request.ProcessStatus,
                    ProcessProgress = request.ProcessProgress,
                    StartTime = request.StartTime,
                    EndTime = request.EndTime,
                    ReportHours = request.ReportHours,
                    ReportMinutes = request.ReportMinutes,
                    PricingMethod = request.PricingMethod,
                    WageUnitPrice = request.WageUnitPrice,
                    EstimatedWage = request.EstimatedWage,
                    BonusAmount = request.BonusAmount,
                    PenaltyAmount = request.PenaltyAmount,
                    CreateTime = DateTime.Now,
                    CreatorId = request.CreatorId,
                    IsDeleted = false
                };

                // 自动计算效率相关字段
                CalculateEfficiencyFields(workReport);

                var insertResult = await _workReportRepo.CreateAsync(workReport);
                if (insertResult <= 0)
                {
                    res.Code = ApiEnum.Fail;
                    res.Msg = "新增报工失败";
                    return res;
                }

                // 不良品项
                int defectiveRows = 0;
                if (request.DefectiveItems != null && request.DefectiveItems.Any())
                {
                    // 若插入后仍未获得 Id，则尝试查询
                    var workReportId = workReport.Id;
                    if (workReportId == 0)
                    {
                        workReportId = _workReportRepo.GetAll()
                            .Where(x => x.WorkOrderCode == request.WorkOrderCode && x.CreateTime == workReport.CreateTime)
                            .Select(x => x.Id).ToList().FirstOrDefault();
                    }

                    var defectiveEntities = request.DefectiveItems.Select(d => new DomainWorkReportDefectiveItem
                    {
                        WorkReportId = workReportId,
                        DefectiveCode = d.DefectiveCode,
                        DefectiveQty = d.DefectiveQty,
                        CreateTime = DateTime.Now,
                        CreatorId = request.CreatorId,
                        IsDeleted = false
                    }).ToList();

                    defectiveRows = await _defectiveItemRepo.CreateBatchAsync(defectiveEntities);
                }

                // 报工成功后自动创建工作流实例（完工单）
                await CreateWorkflowInstanceAsync(workReport, request);

                scope.Complete();

                res.Code = ApiEnum.Success;
                res.Msg = "新增报工成功";
                res.Data = insertResult + defectiveRows;
                return res;
            }
            catch (Exception ex)
            {
                res.Code = ApiEnum.Error;
                res.Msg = $"新增报工异常：{ex.Message}";
                return res;
            }
        }

        /// <summary>
        /// 根据报工信息创建工作流实例（完工单）
        /// </summary>
        /// <param name="workReport">报工记录</param>
        /// <param name="request">报工请求</param>
        private async Task CreateWorkflowInstanceAsync(DomainWorkReport workReport, AddWorkReportCommand request)
        {
            // 生成唯一的工作流ID
            var workflowId = $"WF-{DateTime.Now:yyyyMMddHHmmss}-{workReport.Id}";
            
            // 生成唯一工单编号（基于工单编号 + 工序名称）
            var workOrderNo = $"{request.WorkOrderCode}-{request.ProcessName}";
            
            // 根据工序名称生成简单的工序编码
            var processCode = GenerateProcessCode(request.ProcessName);
            
            // 准备表单数据（将报工信息序列化为JSON）
            var formData = new
            {
                WorkReportId = workReport.Id,
                WorkOrderCode = request.WorkOrderCode,
                WorkOrderNo = workOrderNo,
                ProcessName = request.ProcessName,
                ProcessCode = processCode,
                ProductCode = request.ProductCode,
                ProductName = request.ProductName,
                ReportQty = request.ReportQty,
                GoodQty = request.GoodQty,
                BadQty = request.DefectiveQty,
                DefectReason = request.DefectiveItems?.Any() == true ? 
                    string.Join(";", request.DefectiveItems.Select(x => x.DefectiveCode)) : null,
                Producer = request.Producer,
                WorkHours = (decimal)request.ReportHours + (decimal)request.ReportMinutes / 60,
                StartTime = request.StartTime,
                EndTime = request.EndTime,
                CompletionTime = DateTime.Now,
                Remark = $"工序状态：{request.ProcessStatus}，进度：{request.ProcessProgress}"
            };

            var workflowInstance = new WorkflowInstanceModel
            {
                WorkOrderCode = request.WorkOrderCode,
                WorkOrderNo = workOrderNo,
                ProcessName = request.ProcessName,
                ProcessCode = processCode,
                Title = $"{request.ProcessName}完工审批",
                WorkflowId = workflowId,
                StepId = "S1",
                StepName = "提交审批",
                AuditUserId = null,
                AuditUserName = null,
                DefinitionId = "WORK_COMPLETION_DEF",
                Version = 1,
                ApplicantUserName = request.Producer,
                FormData = JsonSerializer.Serialize(formData, new JsonSerializerOptions 
                { 
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
                }),
                Status = "发起",
                CompletedTime = null,
                CreateTime = DateTime.Now,
                CreatorId = request.CreatorId,
                IsDeleted = false
            };

            await _workflowInstanceRepo.CreateAsync(workflowInstance);
        }

        /// <summary>
        /// 根据工序名称生成工序编码
        /// </summary>
        /// <param name="processName">工序名称</param>
        /// <returns>工序编码</returns>
        private string GenerateProcessCode(string processName)
        {
            // 简单的工序编码生成逻辑，实际项目中可能需要从主数据表查询
            var codeMap = new Dictionary<string, string>
            {
                ["焊接"] = "WELD",
                ["装配"] = "ASSY",
                ["检测"] = "TEST",
                ["包装"] = "PACK",
                ["喷涂"] = "PAINT",
                ["切割"] = "CUT",
                ["钻孔"] = "DRILL",
                ["打磨"] = "GRIND"
            };

            if (codeMap.ContainsKey(processName))
            {
                return codeMap[processName];
            }

            // 如果没有预定义的编码，使用工序名称的拼音首字母 + 时间戳
            return $"PROC_{DateTime.Now:yyyyMMddHHmmss}";
        }

        /// <summary>
        /// 自动计算效率相关字段
        /// </summary>
        /// <param name="workReport">报工记录</param>
        private void CalculateEfficiencyFields(DomainWorkReport workReport)
        {
            // 计算总工时（小时）
            decimal totalHours = workReport.ReportHours + (decimal)workReport.ReportMinutes / 60;
            
            if (totalHours > 0 && workReport.ReportQty > 0)
            {
                // 实际效率 = 产量 / 工时（件/小时）
                workReport.ActualEfficiency = Math.Round(workReport.ReportQty / totalHours, 2);
                
                // 标准效率暂时设为固定值，实际项目中应从工序标准工时表获取
                // 这里假设标准效率为每小时10件
                workReport.StandardEfficiency = 10;
                
                // 达标率 = (实际效率 / 标准效率) × 100%
                if (workReport.StandardEfficiency > 0)
                {
                    workReport.ComplianceRate = Math.Round((workReport.ActualEfficiency / workReport.StandardEfficiency) * 100, 2);
                }
                else
                {
                    workReport.ComplianceRate = 0;
                }
            }
            else
            {
                // 如果工时或产量为0，则效率为0
                workReport.StandardEfficiency = 10; // 保持标准值
                workReport.ActualEfficiency = 0;
                workReport.ComplianceRate = 0;
            }
        }
    }
} 